package day24.map;

import java.util.*;

public class DouDiZhu {
    public static void main(String[] args) {
        // 定义扑克牌的数字和花色
        // numbers数组按照斗地主规则从小到大排列（不包括2、小王、大王）
        String[] numbers = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
        // colors数组定义四种花色：黑桃(♠)、红桃(♥)、梅花(♣)、方块(♦)
        String[] colors = {"♠", "♥", "♣", "♦"};
        
        // 创建Map存储牌的大小顺序，用于后续排序
        // 在斗地主中，牌的大小顺序为：3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王
        Map<String, Integer> orderMap = new HashMap<>();
        String[] order = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2", "小王", "大王"};
        for (int i = 0; i < order.length; i++) {
            orderMap.put(order[i], i);
        }
        
        // 创建54张扑克牌的集合
        List<String> poker = new ArrayList<>();
        
        // 添加普通牌：每种数字有四种花色，共13*4=52张
        // 双重循环遍历所有数字和花色组合，生成52张普通牌
        for (String number : numbers) {
            for (String color : colors) {
                // 将花色和数字拼接成一张牌，如"♠3"、"♥A"等
                poker.add(color + number);
            }
        }
        
        // 添加大小王：斗地主特有的两张王牌
        // 大小王在斗地主中是特殊牌型，没有花色，直接添加
        poker.add("小王");
        poker.add("大王");
        
        System.out.println("初始牌组：" + poker);
        
        // 洗牌：使用Collections工具类的shuffle方法随机打乱牌组顺序
        // shuffle方法会随机重新排列List中的元素，模拟洗牌过程
        Collections.shuffle(poker);
        
        // 创建三个玩家和底牌的集合
        // 每个玩家17张牌，剩余3张作为底牌
        List<String> player1 = new ArrayList<>();
        List<String> player2 = new ArrayList<>();
        List<String> player3 = new ArrayList<>();
        List<String> dipai = new ArrayList<>();
        
        // 发牌：每人17张，剩余3张作为底牌
        // 通过取模运算确定当前牌发给哪个玩家
        for (int i = 0; i < poker.size(); i++) {
            // 当索引大于等于51时，表示是最后三张牌，作为底牌
            if (i >= 51) {
                dipai.add(poker.get(i)); // 底牌：最后三张牌
            } else {
                // 计算发给哪个玩家：0-玩家1，1-玩家2，2-玩家3
                // 使用取模运算符(%)实现轮流发牌的效果
                int playerIndex = i % 3; 
                switch (playerIndex) {
                    case 0:
                        player1.add(poker.get(i));
                        break;
                    case 1:
                        player2.add(poker.get(i));
                        break;
                    case 2:
                        player3.add(poker.get(i));
                        break;
                }
            }
        }
        
        // 对每个玩家的手牌进行排序，按照斗地主规则从大到小排列
        // 调用自定义的排序方法，传入玩家手牌和牌大小映射表
        sortCards(player1, orderMap);
        sortCards(player2, orderMap);
        sortCards(player3, orderMap);
        
        // 对底牌进行排序，确保底牌也按规则排列
        sortCards(dipai, orderMap);
        
        // 展示结果：输出每个玩家的手牌和底牌
        System.out.println("\n玩家1的手牌：" + player1);
        System.out.println("\n玩家2的手牌：" + player2);
        System.out.println("\n玩家3的手牌：" + player3);
        System.out.println("\n底牌：" + dipai);
    }
    
    // 根据斗地主规则对手牌进行排序的方法
    // 参数cards：需要排序的牌组
    // 参数orderMap：牌大小顺序映射表
    public static void sortCards(List<String> cards, Map<String, Integer> orderMap) {
        // 使用Collections.sort方法对牌组进行排序
        // 传入自定义的比较器Comparator实现特定排序规则
        Collections.sort(cards, new Comparator<String>() {
            @Override
            public int compare(String card1, String card2) {
                // 提取牌的数字/字符部分进行比较
                // getCardNumber方法用于从完整牌面中提取数字部分
                String num1 = getCardNumber(card1);
                String num2 = getCardNumber(card2);
                
                // 根据orderMap中定义的顺序进行比较，实现从大到小排序
                // 通过获取每张牌在orderMap中的值来比较大小
                // 返回负数表示第一个元素小于第二个元素，正数表示大于，0表示相等
                return orderMap.get(num1).compareTo(orderMap.get(num2));
            }
        });
    }
    
    // 从牌面中提取数字/字符部分的工具方法
    // 参数card：一张牌的字符串表示，如"♠3"、"♥A"、"小王"等
    // 返回值：牌的数字或特殊名称，如"3"、"A"、"小王"等
    public static String getCardNumber(String card) {
        // 特殊处理大小王：大小王没有花色，直接返回原字符串
        if (card.equals("小王") || card.equals("大王")) {
            return card;
        }
        
        // 去掉花色，获取数字
        // 判断是否以花色开头，如果是则去掉第一个字符（花色）得到数字
        // startsWith方法用于检查字符串是否以指定前缀开始
        if (card.startsWith("♠") || card.startsWith("♥") || card.startsWith("♣") || card.startsWith("♦")) {
            // substring(1)方法用于截取从索引1开始到末尾的子字符串
            // 即去掉第一个字符（花色），保留数字部分
            return card.substring(1);
        }
        
        // 如果不匹配以上条件，直接返回原字符串
        return card;
    }
}